Option Explicit

'################################################################
' Discriptor
' 筛选器组合的执行器
'################################################################

' 随机列名长度
Private Const RANDOM_ALIAS_NAME_SIZE As Integer = 15
' 分组数量列的列名
Private Const DF_COL_NAME_GROUP_COUNT As String = "@@@GroupCount@@@"
' group Key 中各列结果的分隔符
Private Const GROUP_KEY_COL_DELIMITER As String = "@@@,"

' 各个列的真实类型名称常量
' 因为 Map 中无法保存常量，所以在这里以数值型常量进行替代
' 字面量列
Private Const COL_TYPE_LITERAL_COL As Integer = 1
' 真实列
Private Const COL_TYPE_REAL_COL As Integer = 2
' 计算列
Private Const COL_TYPE_COMPUTE_COL As Integer = 3
' 聚合列
Private Const COL_TYPE_AGG_COL As Integer = 4
' 组合式聚合列
Private Const COL_TYPE_COMPOSITE_AGG_COL As Integer = 5

'################################################################
' Enum
'################################################################
' 由 COL_TYPE_* 常量进行替代，后续不再使用
'Private Enum COL_TYPE
'    ' 字面量列
'    LITERAL_COL = 1
'    ' 真实列
'    REAL_COL = 2
'    ' 计算列
'    COMPUTE_COL = 3
'    ' 聚合列
'    AGG_COL = 4
'    ' 组合式聚合列
'    COMPOSITE_AGG_COL = 5
'End Enum

'################################################################
' Field
'################################################################
'---------------------------
' 基础数据
'---------------------------
' join + main 的条件执行器组合
' IDFFilterConditionExecutor[]
Private conditionExecutors() As IDFFilterConditionExecutor

' 执行器的数量
Private conditionExecutorCount As Integer

' mainFilter 的条件执行器
Private fieldMainConditionExecutor As IDFFilterConditionExecutor

' 保存原始 join 执行器列表中的最后一个 Right join 执行器
' 如果不存在 right join，则当前属性为 Nothing
Private lastRightJoinExecutor As DFFilterRightJoinExecutor

' 需要的筛选列
' 存在为 Nothing 的情况
'
' List<IDFFilterCol>
Private fieldSelectCols As Collection

' 用于分组的列
' 存在为 Nothing 的情况
'
' HashSet<IDFFilterCol>
Private fieldGroupByCols As ISet
' fieldGroupByCols 的 Value 构成的数组，以降低每次计算时访问 fieldGroupByCols 的消耗
' IDFFilterCol[]
Private groupbyColArray As Variant
Private groupbyColCount As Integer

Private fieldMainFilter As DFFilter

'---------------------------
' 标志位
'---------------------------
' 是否需要分组
' 聚合列 + groupby 存在一个就是 true
Private needGroup As Boolean

' 是否存在聚合列
' 包括基础聚合列 + 从组合式聚合列中剥离出来的聚合列
Private hasAggCol As Boolean

' 是否需要记录各个 Filter 的活动行索引
'    如果 selectCol 中存在真实列，则为 True
'    如果组合式聚合列中的非聚合列的底层存在真实列，则为 True
Private needRecordFilterIndex As Boolean

' 表示是否存在某个组合式聚合列内的非聚合列的底层使用了真实列
Private existUsedRealColInCompositeAggCol As Boolean

'---------------------------
' 缓存数据
'---------------------------
' 当前 Filter 中使用到的 Filter
' 启动 exec 后，在当前 Filter 内收集（包括当前 Filter 自身 + Join执行器中的Filter）
' 未执行 exec 时，是 Nothing
'
' Set<DFFilter>
Private usedFilters As ISet

' 用来保存: 真实列、计算列、组合式聚合列中的非聚合列使用到的 Filter
' HashSet<DFFilter>
Private recordIndexFilterSet As ISet
' recordIndexFilterSet 的 Value 构成的数组，以降低每次计算时访问各Filter 的活动行时的消耗
' DFFilter[]
' DFFilter 的顺序最终将会和 indexDF 缓存中列的顺序一致
Private recordIndexFilterArray As Variant
Private recordIndexFilterCount As Integer

' 真实列缓存
' Map<列别名, IDFFilterCol>
Private realColMap As Object

' 计算列缓存
' Map<别名, IDFFilterCol>
Private computeColMap As Object
' computeColMap 的 Value 构成的数组，以降低每次计算时访问 computeColMap 的消耗
Private computeColArray As Variant
Private computeColCount As Integer

' 聚合列缓存
' Map<别名, IDFFilterAggCol>
Private aggColMap As Object
' aggColMap 的 Value 构成的数组，以降低每次计算时访问 aggColMap 的消耗
Private aggColArray As Variant
Private aggColCount As Integer

' 组合式聚合列缓存
' Map<别名, IDFFilterAggCol>
Private compositeAggColMap As Object
' compositeAggColMap 的 Value 构成的数组，以降低每次计算时访问 compositeAggColMap 的消耗
Private compositeAggColArray As Variant
Private compositeAggColCount As Integer

' 组合式聚合列中包含的基础聚合列
' Map<别名, IDFFilterAggCol>
Private inCompositeAggColMap As Object
' inCompositeAggColMap 的 Value 构成的数组，以降低每次计算时访问 inCompositeAggColMap 的消耗
Private inCompositeAggColArray As Variant
Private inCompositeAggColCount As Integer

' 各个列真实类型的记录
' Map<列的别名, 类型枚举>
Private colTypeMap As LinkedHashMap

'---------------------------
' 计算结果数据
'---------------------------
' 包含了整体筛选结果索引集合的 DataFrame
' 列名是各个 Filter 的别名
' 内容是所有 Filter 组合之后，各 Filter 的数据索引
' 对于 Left/Right join 连接失败产生的空引用，使用: DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL
'
' 生成的列的顺序和 recordIndexFilterArray 中的顺序相同
Private indexDF As IDataFrame

' 真实列的索引式切片缓存
' Map<"列别名", 该列的索引式切片对象>
Private realColIndexedSliceMap As Object

' 计算列 + 聚合列数据缓存
' 前面的列保存的是计算列的结果，后面的列保存的是聚合列的计算结果
Private computedDataDF As IDataFrame

' 保存 group key 及其在 `indexDF` + `computedDataDF` 中的行索引映射
' Map<"GroupKey", 行索引>
Private groupKeyToIndexMap As Object

' 结果集的最大行索引
Private maxResultRowIndex As Long

' 保存组合式聚合列的结果
Private compositeAggDF As IDataFrame

'################################################################
' Constructor
'################################################################
Private Sub Class_Initialize()
    needRecordFilterIndex = False
    existUsedRealColInCompositeAggCol = False
    computeColCount = 0
    aggColCount = 0
    groupbyColCount = 0
    recordIndexFilterCount = 0
    compositeAggColCount = 0
    inCompositeAggColCount = 0
    ' 最大行索引默认初始化为 -1
    maxResultRowIndex = -1
End Sub

Private Sub Class_Terminate()
    ' 清除所有缓存数据
    Set usedFilters = Nothing
    Set recordIndexFilterSet = Nothing
    Set realColMap = Nothing
    Set computeColMap = Nothing
    Set aggColMap = Nothing
    Set compositeAggColMap = Nothing
    Set colTypeMap = Nothing
    Set indexDF = Nothing
    Set realColIndexedSliceMap = Nothing
    Set computedDataDF = Nothing
    Set groupKeyToIndexMap = Nothing
End Sub

'################################################################
' Init
'################################################################
' @param mainFilter
' @param mainConditionExecutor mainFilter 中的条件执行器(可能为空)
' @param joinExecutors 连接执行器集合 (可能为空)
' @param selectCols 筛选项集合 (可能为空)
' @param groupByCols 分组项集合 (可能为空)
Public Sub Init(ByRef mainFilter As DFFilter, _
    ByRef mainConditionExecutor As IDFFilterConditionExecutor, _
    ByRef joinExecutors As Collection, _
    ByRef selectCols As Collection, _
    ByRef groupByCols As ISet)

    ' 1. 检查参数
    If mainFilter Is Nothing Then
        Err.Raise 10001, Description:="parameter mainFilter must be not nothing"
        Exit Sub
    End If

    ' 2. 执行筛选前，对筛选内容进行预处理
    checkInitParam mainFilter, mainConditionExecutor, _
                    joinExecutors, selectCols, groupByCols

    ' 3. 临时保存参数
    Set fieldMainFilter = mainFilter
    Set fieldGroupByCols = groupByCols
    Set fieldSelectCols = selectCols

    ' 保存 mainFilter 的条件执行器
    ' 如果执行器为空，则需要手动创建一个无条件的执行器
    If mainConditionExecutor Is Nothing Then
        Dim tempMainExecutor As DFFilterMainConditionExecutor
        Set tempMainExecutor = New DFFilterMainConditionExecutor
        tempMainExecutor.Init mainFilter
        Set fieldMainConditionExecutor = tempMainExecutor
    Else
        Set fieldMainConditionExecutor = mainConditionExecutor
    End If

    ' 4. 分拣所有的列对象
    ensureSelectColType

    ' 5. 按照使用的 Filter 数量及其内容，对所有的 join 进行排序
    '    并生成最终用来筛选数据的条件执行器
    sortAndCreateConditionExecutors joinExecutors

    ' 6. 搜索最后一个 right join 执行器
    findLastRightJoinExecutor joinExecutors
End Sub

'################################################################
' Function
'################################################################
'---------------------------
' 检查初始化参数
'---------------------------
' 对初始化内容进行预检
Private Sub checkInitParam( _
    ByRef mainFilter As DFFilter, _
    ByRef mainConditionExecutor As IDFFilterConditionExecutor, _
    ByRef joinExecutors As Collection, _
    ByRef selectCols As Collection, _
    ByRef groupByCols As Collection)

    ' 1. 保证 main + join 的别名不重名
    '     并收集当前筛选器中需要使用到的 Filter
    collectUsedFilterFromDataSource mainFilter, joinExecutors

    ' 2. 检查需要 select 的各个列的数据源 Filter 是否都存在
    assertFilterExistForSelectCol selectCols

    ' 3. 检查所有条件中使用的数据源 Filter 是否都存在
    assertFilterExistForCondition mainConditionExecutor, joinExecutors

    ' 4. 检查 groupby 列中的数据源 Filter 是否都存在
    assertFilterExistForGroupByCol groupByCols

    ' 5. 检查是否存在同名列
    assertNotSameNameSelectCol selectCols
End Sub

' 保证 main + join 的别名不重名
' 并收集当前筛选器中需要使用到的 Filter
Private Sub collectUsedFilterFromDataSource( _
    ByRef mainFilter As DFFilter, _
    ByRef joinExecutors As Collection)

    ' 1. 需要检查所有 Filter 中是否存在重名的问题
    Dim nameSet As ISet
    Dim result As ISet
    Set nameSet = UtilsSet.createHashSet
    Set result = UtilsSet.createHashSet

    result.Add mainFilter
    nameSet.Add mainFilter.AliasName

    If Not joinExecutors Is Nothing Then
        Dim elem As Variant
        Dim joinExecutor As IDFFilterJoinExecutor
        Dim f As DFFilter
        For Each elem In joinExecutors
            Set joinExecutor = elem
            Set f = joinExecutor.JoinFilter
            If nameSet.Exists(f.AliasName) Then
                Err.Raise 10308, Description:="Ambiguous Filter reference. FilterName=" & f.AliasName
                Exit Sub
            End If

            result.Add f
            nameSet.Add f.AliasName
        Next
    End If

    Set usedFilters = result
End Sub

' 保证 select 的各个列的数据源 Filter 都存在
Private Sub assertFilterExistForSelectCol(ByRef selectCols As Collection)
    ' 1. 如果没有设置任何筛选项（保留所有列），则立刻停止
    If selectCols Is Nothing Then
        Exit Sub
    End If

    ' 2. 遍历所有筛选项，并进行检查
    Dim elem As Variant
    Dim c As IDFFilterCol
    Dim f As Variant
    Dim tempSet As ISet
    For Each elem In selectCols
        Set c = elem
        ' 2.1 如果是字面量，则忽略
        If c.isLiteralCol Then
            Goto continue1
        End If

        ' 2.2 如果筛选项只使用了一个Filter，则直接检查这个 Filter 是否存在
        If c.isUseSingleFilter Then
            If Not usedFilters.Exists(c.Filter) Then
                Err.Raise 10305, Description:="Can not find the filter of select col in main or join. " & vbCrLf & _
                                "Not Find Filter.Name=" & c.Filter.AliasName
                Exit Sub
            End If

            Goto continue1
        End If

        ' 2.3 如果筛选项使用了多个 Filter，则需要逐个检查
        Set tempSet = c.getAllFilters
        For Each f In tempSet.Items
            If Not usedFilters.Exists(f) Then
                Err.Raise 10305, Description:="Can not find the filter of select col in main or join. " & vbCrLf & _
                                "Not Find Filter.Name=" & f.AliasName

                Exit Sub
            End If
        Next

continue1:
    Next
End Sub

' 保证所有条件中使用的数据源 Filter 都存在
Private Sub assertFilterExistForCondition( _
    ByRef mainConditionExecutor As IDFFilterConditionExecutor, _
    ByRef joinExecutors As Collection)

    Dim f As Variant 'DFFilter
    Dim i As Integer
    Dim tempSet As ISet

    ' 1. 检查 where 条件
    If Not mainConditionExecutor Is Nothing Then
        Set tempSet = mainConditionExecutor.getAllFilters
        For Each f In tempSet.Items
            If Not usedFilters.Exists(f) Then
                Err.Raise 10305, Description:="Can not find the filter of the where condition in main or join. " & vbCrLf & _
                                "Not Find Filter.Name=" & f.AliasName

                Exit Sub
            End If
        Next

    End If

    ' 2. 检查所有 join 中的条件
    If Not joinExecutors Is Nothing Then
        Dim elem As Variant
        Dim joinExecutor As IDFFilterConditionExecutor
        For Each elem In joinExecutors
            Set joinExecutor = elem
            Set tempSet = joinExecutor.getAllFilters

            For Each f In tempSet.Items
                If Not usedFilters.Exists(f) Then
                    Err.Raise 10305, Description:="Can not find the filter of the where condition in main or join. " & vbCrLf & _
                                    "Error in join condition, JoinFilter.Name=" & joinExecutor.Filter.AliasName & "." & vbCrLf & _
                                    "Not Find Filter.Name=" & f.AliasName
                    Exit Sub
                End If
            Next

        Next
    End If
End Sub

' 保证 groupby 列中的数据源 Filter 都存在
Private Sub assertFilterExistForGroupByCol( _
    ByRef groupByCols As Collection)
    ' 1. 如果没有设置任何分组列，则立刻停止
    If groupByCols Is Nothing Then
        Exit Sub
    End If

    ' 2. 遍历所有筛选项，并进行检查
    Dim elem As Variant
    Dim c As IDFFilterCol
    Dim f As Variant 'DFFilter
    Dim tempSet As ISet
    For Each elem In groupByCols
        Set c = elem
        ' 2.1 如果是字面量，则忽略
        If c.isLiteralCol Then
            Goto continue1
        End If

        ' 2.2 如果筛选项只使用了一个Filter，则直接检查这个 Filter 是否存在
        If c.isUseSingleFilter Then
            If Not usedFilters.Exists(c.Filter) Then
                Err.Raise 10305, Description:="Can not find the filter of groupby col in main or join. " & vbCrLf & _
                                "Not Find Filter.Name=" & c.Filter.AliasName
                Exit Sub
            End If

            Goto continue1
        End If

        ' 2.3 如果筛选项使用了多个 Filter，则需要逐个检查
        Set tempSet = c.getAllFilters
        For Each f In tempSet.Items
            If Not usedFilters.Exists(f) Then
                Err.Raise 10305, Description:="Can not find the filter of groupby col in main or join. " & vbCrLf & _
                                "Not Find Filter.Name=" & f.AliasName
                Exit Sub
            End If
        Next

continue1:
    Next
End Sub

' 保证不存在同名列
Private Sub assertNotSameNameSelectCol(ByRef selectCols As Collection)
    ' 1. 如果没有设置 selectCols，则需要保证所有 Filter 中不存在同名列
    If selectCols Is Nothing Then
        assertNotSameNameColInAllFilter
        Exit Sub
    End If

    ' 2. 检查所有 selectCols
    Dim tempSet As ISet
    Set tempSet = UtilsSet.createHashSet

    Dim elem As Variant
    Dim c As IDFFilterCol
    For Each elem In selectCols
        Set c = elem
        ' 忽略未设置别名的列，这些列将在最终生成结果时设置一个随机名称
        If c.AliasName = "" Then
            Goto continue1
        End If

        If tempSet.Exists(c.AliasName) Then
            Err.Raise 10307, Description:="Ambiguous column reference. ColumnName=" & c.AliasName
            Exit Sub
        End If

        tempSet.Add c.AliasName
continue1:
    Next
End Sub

' 保证所有 Filter 中的 DataFrame 中不存在同名的列
Private Sub assertNotSameNameColInAllFilter()
    Dim f As Variant 'DFFilter

    Dim tempSet As ISet
    Set tempSet = UtilsSet.createHashSet

    ' 遍历每个 DataFilter，检查是否存在同名列
    Dim cName As Variant
    For Each f In usedFilters.Items
        For Each cName In f.MainDataFrame.ColumnNames

            If tempSet.Exists(cName) Then
                Err.Raise 10307, Description:="Ambiguous column reference. Column.Name=" & cName & ", Filter.Name=" & f.AliasName
                Exit Sub
            End If

            tempSet.Add cName
        Next
    Next
End Sub

' 分拣所有的列对象
Private Sub ensureSelectColType()
    Dim f As Variant 'DFFilter
    Dim cElem As Variant
    Dim c As IDFFilterCol

    ' 1. 初始化列类型缓存
    Set colTypeMap = New LinkedHashMap

    ' 2. 如果没有设置 selectCol
    If fieldSelectCols Is Nothing Then
        Set fieldSelectCols = New Collection
        Set realColMap = UtilsCreateSysObj.createMap

        For Each f In usedFilters.Items
            For Each cElem In f.allCols
                Set c = cElem
                ' 需要获取所有 main + join Filter 中的所有列作为结果
                fieldSelectCols.Add c
                ' 全部列都保存到真实列缓存 `realColMap` 中
                realColMap.Add c.AliasName, c
                ' 保存列类型
                colTypeMap.Add c.AliasName, COL_TYPE_REAL_COL
            Next

            ' 缓存 recordIndexFilterSet 需要保存所有 Filter
            If recordIndexFilterSet Is Nothing Then
                Set recordIndexFilterSet = UtilsSet.createHashSet
            End If
            recordIndexFilterSet.Add f
        Next

        Exit Sub
    End If

    ' 3. 遍历 selectCol 并分拣
    For Each cElem In fieldSelectCols
        Set c = cElem

        ' 3.1 如果某个列对象没有别名，则随机生成一个，并保存
        If c.AliasName = "" Then
            c.alias UtilsRandom.enNumStr(RANDOM_ALIAS_NAME_SIZE)
        End If

        ' 3.2 字面量列，不做处理
        '     因为字面量列中也存在形如 `Max(1) + 2` 这种形式
        '     所有需要同时满足即是字面量列，又不是聚合列的条件组合
        If c.isLiteralCol = True And c.isAggregateCol = False Then
            ' 缓存列类型
            colTypeMap.Add c.AliasName, COL_TYPE_LITERAL_COL
            Goto continue1
        End If

        ' 3.3 真实列
        If TypeOf c Is DFFilterSingleCol Then
            If realColMap Is Nothing Then
                Set realColMap = UtilsCreateSysObj.createMap
            End If

            ' 缓存自身
            realColMap.Add c.AliasName, c
            ' 缓存列类型
            colTypeMap.Add c.AliasName, COL_TYPE_REAL_COL
            ' 缓存当前列使用 Filter 名称
            If recordIndexFilterSet Is Nothing Then
                Set recordIndexFilterSet = UtilsSet.createHashSet
            End If
            recordIndexFilterSet.Add c.Filter

            Goto continue1
        End If

        ' 3.4 计算列需要缓存到 computeColMap
        '     即计算列，又不能是聚合列
        If ((TypeOf c Is IDFFilterSingleComputeCol) Or (TypeOf c Is IDFFilterDoubleComputeCol)) _
            And c.isAggregateCol = False Then
            If computeColMap Is Nothing Then
                Set computeColMap = UtilsCreateSysObj.createMap
            End If

            ' 缓存自身
            computeColMap.Add c
            ' 缓存列类型
            colTypeMap.Add c.AliasName, COL_TYPE_COMPUTE_COL
            ' 缓存当前列使用 Filter 名称
            For Each f In c.getAllFilters.Items
                If recordIndexFilterSet Is Nothing Then
                    Set recordIndexFilterSet = UtilsSet.createHashSet
                End If
                recordIndexFilterSet.Add f
            Next

            Goto continue1
        End If

        ' 3.5 聚合列需要缓存到 aggColMap
        If TypeOf c Is IDFFilterAggCol Then
            If aggColMap Is Nothing Then
                Set aggColMap = UtilsCreateSysObj.createMap
            End If

            ' 缓存自身
            aggColMap.Add c.AliasName, c
            ' 缓存列类型
            colTypeMap.Add c.AliasName, COL_TYPE_AGG_COL

            Goto continue1
        End If

        ' 3.6 组合式聚合列 需要缓存到 compositeAggColMap
        If c.isAggregateCol = True Then
            If compositeAggColMap Is Nothing Then
                Set compositeAggColMap = UtilsCreateSysObj.createMap
            End If

            ' 缓存自身
            compositeAggColMap.Add c.AliasName, c
            ' 缓存列类型
            colTypeMap.Add c.AliasName, COL_TYPE_COMPOSITE_AGG_COL
            ' 分解当前列
            splitCompositeAggCol c

            Goto continue1
        End If

        ' 3.7 出现了无法识别的列，抛出异常
        Err.Raise 10309, Description:="Can not recognize column's type. Column.Name=" & c.AliasName & ", Column.AliasName=" & c.AliasName
        Exit Sub
continue1:
    Next
End Sub

' 分解组合式聚合列
' (Max(1) + c2) + ((Max(2) + c3) + c3)
' @param c 组合式聚合列
'           该列一定是单列计算列或者多列计算列中的一种，然后在内部存在被包装的基础聚合列
Private Sub splitCompositeAggCol(ByRef c As Variant)
    ' 1. 如果是基础聚合列，则缓存
    If TypeOf c Is IDFFilterAggCol Then
        ' 如果这个列还没有别名，则随机生成一个
        If elemCol.AliasName = "" Then
            elemCol.alias UtilsRandom.enNumStr(RANDOM_ALIAS_NAME_SIZE)
        End If

        ' 缓存自身
        If aggColMap Is Nothing Then
            Set aggColMap = UtilsCreateSysObj.createMap
        End If
        aggColMap.Add elemCol.AliasName, elemCol

        If inCompositeAggColMap Is Nothing Then
            Set inCompositeAggColMap = UtilsCreateSysObj.createMap
        End If
        inCompositeAggColMap.Add elemCol.AliasName, elemCol

        ' 结束递归
        Exit Sub
    End If

    ' 2. 检查这个列是不是聚合列，如果不是，则需要开始收集相关信息
    If c.isAggregateCol = False Then
        Dim isColInGroup As Boolean
        Dim tempSet As ISet
        Set tempSet = c.getRealUsedCol

        ' 如果没有使用真实列，则结束递归
        If tempSet.Count = 0 Then
            Exit Sub
        End If

        ' 检查真实列是否都在 groupby 中
        Dim tempSetItems As Variant
        Dim tempCol As IDFFilterCol
        Dim i As Integer
        tempSetItems = tempSet.Items
        For i = 0 To (tempSet.Count - 1)
            Set tempCol = tempSetItems(i)
            ' 如果不存在 groupby 或者列不在 groupby 中，则需要抛出异常
            If fieldGroupByCols Is Nothing Then
                isColInGroup = False
            Else
                isColInGroup = (fieldGroupByCols.Exists(tempCol))
            End If

            If isColInGroup = False Then
                Err.Raise 10306, Description:="Find a column not in groupby column." & vbCrLf & _
                "Error col.Name="& tempCol.Name & _
                ", col.AliasName=" & tempCol.AliasName & _
                ", filter.Name" & tempCol.Filter.Name & _
                ", filter.AliasName" & tempCol.Filter.AliasName
                Exit Sub
            End If

            ' 收集真实列使用的 Filter
            If recordIndexFilterSet Is Nothing Then
                Set recordIndexFilterSet = UtilsSet.createHashSet
            End If
            recordIndexFilterSet.Add tempCol.Filter
        Next

        ' 出现了真实列，表示计算时需要记录各 Filter 的活动行索引
        needRecordFilterIndex = True

        ' 出现了真实列，表示生成最终结果时需要重新定位 Filter 的活动行索引
        existUsedRealColInCompositeAggCol = True

        ' 结束递归
        Exit Sub
    End If

    ' 3. 处理单列 + 多列计算列
    If TypeOf c Is IDFFilterSingleComputeCol Then
        ' 1. 处理单列计算列
        ' 获取原始列并继续检查
        Dim singleCol As IDFFilterSingleComputeCol
        Set singleCol = c
        splitCompositeAggCol singleCol.getComputeCol
    ElseIf TypeOf c Is IDFFilterDoubleComputeCol Then
        ' 2. 处理多列计算列
        ' 获取原始列并继续检查
        Dim doubleCol As IDFFilterDoubleComputeCol
        Set doubleCol = c
        splitCompositeAggCol doubleCol.getLeftComputeCol
        splitCompositeAggCol doubleCol.getRightComputeCol
    End If
End Sub

'---------------------------
' 初始化内置属性 + 缓存
'---------------------------
' 按照使用的 Filter 数量及其内容，对所有的 join 进行排序
' 并生成最终用来筛选数据的条件执行器
'
' 排序方式:
' 以 Main 为起点，搜索只与Main有关的 join 执行器A
' 然后再以找到的join执行器A为起点，搜素只与 Main 有关的 join执行器B
' 直到全部搜索完成
'
' 处理方法
' 1. 创建】【缓存A，开始时，只保存 MainFilter
' 2. 获取所有 join执行器中使用的 Filter 集合
' 3. 遍历 2 中的每一个 Filter 集合，并从中删除【缓存A】中保存的 Filter
'    删除后，如果集合中剩余的 Filter 为 1 个或更少，说明这个执行器与前面的参照目标产生了关联
'    则将这个执行器保存的到最终结果中
'    这个执行器使用的 Filter 保存的到【缓存A】，以便在下一次遍历中作为参照目标
' 4. 重复 3 直到所有执行器都保存到最终结果中
'
' 示例
'   Main=A, Join1=B<A,B>, Join2=C<B,C>, Join3=D<A,D>, Join4=H<C,H>, Join5=J<H,J>
'           Join6=E<B,C,E>, Join7=F<A,E,F>
'   第一次处理: 缓存A=[A]
'           Join1=B<B>, Join2=C<B,C>, Join3=D<D>, Join4=H<C,H>, Join5=J<H,J>
'           Join6=E<B,C,E>, Join7=F<E,F>
'   第一次移动执行器: 最终结果:[B,D], 缓存A=[B,D]
'           Join2=C<B,C>, Join4=H<C,H>, Join5=J<H,J>, Join6=E<B,C,E>, Join7=F<E,F>
'   第二次处理: 缓存A=[B,D]
'           Join2=C<C>, Join4=H<C,H>, Join5=J<H,J>, Join6=E<C,E>, Join7=F<E,F>
'   第二次移动执行器: 最终结果:[B,D,C], 缓存A=[C]
'           Join4=H<C,H>, Join5=J<H,J>, Join6=E<C,E>, Join7=F<E,F>
'   第三次处理: 缓存A=[C]
'           Join4=H<H>, Join5=J<H,J>, Join6=E<E>, Join7=F<E,F>
'   第三次移动执行器: 最终结果:[B,D,C,H,E], 缓存A=[H,E]
'           Join5=J<H,J> Join7=F<E,F>
'   第四次处理: 缓存A=[H,E]
'           Join5=J<J> Join7=F<F>
'   第四次移动执行器: 最终结果:[B,D,C,H,E,J,F]
'
Private Sub sortAndCreateConditionExecutors(ByRef joinExecutors As Collection)

    ' 1. 确定执行器的数量，并创建缓存
    conditionExecutorCount = 0
    If Not joinExecutors Is Nothing Then
        conditionExecutorCount = conditionExecutorCount + joinExecutors.Count
    End If

    conditionExecutorCount = conditionExecutorCount + 1
    ReDim conditionExecutors(0 To (conditionExecutorCount - 1))

    ' 2. 对 Join 执行器进行排序
    If Not joinExecutors Is Nothing Then
        ' 0. 创建 Filter 缓存A，首先需要添加 MainFilter
        Dim filterCache As ISet
        Set filterCache = UtilsSet.createHashSet
        filterCache.Add fieldMainFilter

        ' 1. 获取所有执行器中的 Filter 集合
        '   Map<IDFFilterConditionExecutor, ISet<DFFilter>>
        Dim executorFilterMap As Object
        Set executorFilterMap = UtilsCreateSysObj.createMap

        Dim elem As Variant
        Dim ce As IDFFilterConditionExecutor
        For Each elem In joinExecutors
            Set ce = elem
            executorFilterMap.Add ce, ce.getAllFilters
        Next

        Dim joinIndex As Integer
        joinIndex = 0
        Dim k As Variant
        Dim executeFilterSet As ISet

        ' 用来保存临时的 Filter，以防止在遍历过程中修改 filterCache
        Dim tempSet As ISet
        Set tempSet = UtilsSet.createHashSet

        Dim hasMove As Boolean
        Dim minSize As Integer
        While joinIndex < joinExecutors.Count
            hasMove = False

            ' 遍历每个 executorFilterMap 中的每一个 Filter，
            ' 并从中删除 filterCache 中的每一个 Filter
            For Each k In executorFilterMap.Keys
                Set executeFilterSet = executorFilterMap.Item(k)

                executeFilterSet.RemoveSet filterCache

                ' 如果删除后 set 中剩余的 Filter 小于等于 1
                ' 则将执行器移动到结果中
                If executeFilterSet.Count <= 1 Then
                    ' 保存当前的执行器
                    Set conditionExecutors(joinIndex) = k
                    joinIndex = joinIndex + 1
                    ' 暂存当前执行器中剩余的 Filter，作为下一次遍历需要删除的目标
                    tempSet.MergeSet executeFilterSet
                    ' 从遍历目标中删除
                    executorFilterMap.Remove k

                    hasMove = True
                End If
            Next

            If hasMove Then
                ' 如果已经发生了 Filter 移动，则说明这次遍历搜索到了有效的执行器
                ' 替换缓存A
                filterCache.Clear
                filterCache.MergeSet tempSet
                tempSet.Clear
            Else
                ' 如果没有发生移动，则说明当前的执行器中产生了循环引用
                ' 搜索剩余 Filter 数量最小的执行器

                minSize = 999
                For Each k In executorFilterMap.Values
                    If minSize > k.Count Then
                        minSize = k.Count
                    End If
                Next

                filterCache.Clear

                For Each k In executorFilterMap.Keys
                    Set executeFilterSet = executorFilterMap.Item(k)
                    If executeFilterSet.Item(k).Count = minSize Then
                        ' 保存当前的执行器
                        Set conditionExecutors(joinIndex) = k
                        joinIndex = joinIndex + 1
                        ' 暂存当前执行器中剩余的 Filter，作为下一次遍历需要删除的目标
                        filterCache.MergeSet executeFilterSet
                        ' 从遍历目标中删除
                        executorFilterMap.Remove k
                    End If
                Next
            End If
        Wend
    End If

    ' 3. 将 mainFilter 执行器保存到末尾
    Set conditionExecutors((conditionExecutorCount - 1)) = fieldMainConditionExecutor
End Sub

' 搜索最后一个 right join 执行器
Private Sub findLastRightJoinExecutor(ByRef joinExecutors As Collection)
    If joinExecutors Is Nothing Then
        Exit Sub
    End If

    Dim elem As Variant
    For Each elem In joinExecutors
        If TypeOf elem Is DFFilterRightJoinExecutor Then
            Set lastRightJoinExecutor = elem
        End If
    Next
End Sub
'------------------------------------------------------
' 执行检索
'------------------------------------------------------
' ====================
' 总体控制
' ====================
' 执行筛选
' @return 筛选后数据组成的 DataFrame
Public Function exec() As IDataFrame
    ' 1. 执行预处理
    beforeExec
    ' 2. 执行条件筛选，生成基础结果
    executeCondition
    ' 3. 处理所有未匹配的 right join 中的各行
    executeRightJoinNoMatchedRow
    ' 4. 结束阶段
    afterExec
    ' 5. 生成结果
    Set exec = createResultDF
End Function

' ====================
' 初始化阶段
' ====================
' 执行筛选前，对筛选内容进行预处理
Private Sub beforeExec()
    ' 1. 为了加速实际计算时的速度，将部分 map 缓存展开成数组
    expandCacheToArray

    ' 2. 对所有条件进行预处理
    preExecuteCondition

    ' 3. 初始化标识位
    initFlag

    ' 4. 初始化创建结果集的辅助缓存
    initRecordCache

    ' 5. 为所有聚合列绑定数据源
    bindDataSourceForAggCol
End Sub

' 为了加速实际计算时的速度，将部分 map 缓存展开成数组
Private Sub expandCacheToArray()
    ' 展开缓存，展开后清空原始缓存
    ' 将筛选过程中需要记录活动行索引的 Filter 集合展开成数组
    If Not recordIndexFilterSet Is Nothing Then
        recordIndexFilterArray = recordIndexFilterSet.Items
        recordIndexFilterCount = recordIndexFilterSet.Count

        recordIndexFilterSet.Clear
        Set recordIndexFilterSet = Nothing
    End If

    ' 计算列缓存展开成数组
    If Not computeColMap Is Nothing Then
        computeColArray = computeColMap.Items
        computeColCount = computeColMap.Count

        computeColMap.RemoveAll
        Set computeColMap = Nothing
    End If

    ' 聚合列缓存展开成数组
    If Not aggColMap Is Nothing Then
        aggColArray = aggColMap.Items
        aggColCount = aggColMap.Count

        aggColMap.RemoveAll
        Set aggColMap = Nothing
    End If

    ' 分组列缓存展开成数组
    If Not fieldGroupByCols Is Nothing Then
        groupbyColArray = fieldGroupByCols.Items
        groupbyColCount = fieldGroupByCols.Count

        fieldGroupByCols.Clear
        Set fieldGroupByCols = Nothing
    End If

    ' 组合式聚合列缓存展开成数组
    If Not compositeAggColMap Is Nothing Then
        compositeAggColArray = compositeAggColMap.Items
        compositeAggColCount = compositeAggColMap.Count

        compositeAggColMap.RemoveAll
        Set compositeAggColMap = Nothing
    End If

    If Not inCompositeAggColMap Is Nothing Then
        inCompositeAggColArray = inCompositeAggColMap.Items
        inCompositeAggColCount = inCompositeAggColMap.Count

        inCompositeAggColMap.RemoveAll
        Set inCompositeAggColMap = Nothing
    End If
End Sub

' 对所有条件进行预处理
Private Sub preExecuteCondition()
    Dim e As Variant 'IDFFilterConditionExecutor
    For Each e In conditionExecutors
        e.preExecute
    Next
End Sub

' 初始化标识位
Public Sub initFlag()
    ' 是否需要分组
    ' 聚合列 + groupby 存在一个就是 true
    needGroup = (aggColCount <> 0) Or (groupbyColArray <> 0)

    ' 是否存在聚合列
    ' 包括基础聚合列 + 从组合式聚合列中剥离出来的聚合列
    hasAggCol = (aggColCount <> 0)

    ' 是否需要记录各个 Filter 的活动行索引
    ' 如果 selectCol 中存在真实列，则为 True
    ' 如果组合式聚合列中的非聚合列的底层存在真实列，则为 True
    '
    ' 这个标识位可能会在分解组合时聚合列时设置
    ' 所以如果已经被设置为True了就不需要在做检查了
    If needRecordFilterIndex = False Then
        needRecordFilterIndex = (Not realColMap Is Nothing)
    End If

    ' 是否存在某个组合式聚合列内的非聚合列的底层使用了真实列
    ' existUsedRealColInCompositeAggCol
    ' 该标识位只会在分解组合式聚合列中会被设置为 True，这里不做处理
End Sub

' 初始化创建结果集的辅助缓存
Public Sub initRecordCache()
    ' 1. 初始化Filter索引集合 indexDF
    '    如果没有需要记录活动行索引的 Filter，则不需要初始化
    Dim elem As Variant 'DFFilter
    Dim i As Integer

    If recordIndexFilterCount > 0 Then
        '    每个列的名字就是各个 Filter 的别名
        '    创建列名数组 + 列类型数组(固定为整型数字)
        Dim indexDFColNames() As String
        Dim indexDFColTypes() As DF_DataType
        ReDim indexDFColNames(0 To (recordIndexFilterCount - 1))
        ReDim indexDFColTypes(0 To (recordIndexFilterCount - 1))

        i = 0
        For Each elem In recordIndexFilterArray
            indexDFColNames(i) = elem.AliasName
            indexDFColTypes(i) = DF_DataType.DF_INT
            i = i + 1
        Next

        Dim readIndexDF As DataFrame
        Set readIndexDF = New DataFrame
        readIndexDF.Init colNames:=indexDFColNames, dTypes:=indexDFColTypes

        Set indexDF = readIndexDF
    End If

    ' 2. 创建真实列索引式切片缓存
    If Not realColMap Is Nothing Then
        Set realColIndexedSliceMap = UtilsCreateSysObj.createMap
        Dim tempIndexedSlice As DFSeriesIndexedSlice
        Dim realCol As DFFilterSingleCol

        ' 遍历所有真实列，创建索引式切片
        For Each elem In realColMap.Keys
            Set tempIndexedSlice = New DFSeriesIndexedSlice
            Set realCol = realColMap.Item(elem)
            tempIndexedSlice.Init _
                realCol.DataSource, _
                indexDF.getCol(realCol.IDFFilterCol_Filter.AliasName)

            'tempIndexedSlice.Init _
            '    realCol.Filter.MainDataFrame.getCol(realCol.Name), _
            '    indexDF.getCol(realCol.Filter.AliasName)

            realColIndexedSliceMap.Add elem, tempIndexedSlice
        Next
    End If

    ' 3. 创建 计算列 + 聚合列数据缓存
    '    前面保存
    Dim computedDataDFColCount As Integer
    computedDataDFColCount = computeColCount + aggColCount
    If computedDataDFColCount > 0 Then
        ' 如果 aggColCount 数量大于 0
        ' 需要在末尾额外附加一个列 `groupCount`，用来记录当前这个分组的数量
        If aggColCount > 0 Then
            computedDataDFColCount = computedDataDFColCount + 1
        End If

        ' 初始化信息数组
        Dim computedDataDFColNames() As String
        Dim computedDataDFColTypes() As DF_DataType
        ReDim computedDataDFColNames(0 To (computedDataDFColCount - 1))
        ReDim computedDataDFColTypes(0 To (computedDataDFColCount - 1))

        ' 收集计算列的信息
        Dim tempCol As IDFFilterCol
        For i = 0 To (computeColCount - 1)
            Set tempCol = computeColArray(i)
            computedDataDFColNames(i) = tempCol.AliasName
            computedDataDFColTypes(i) = tempCol.ColType
        Next

        ' 收集聚合列的信息
        For i = 0 To (aggColCount - 1)
            Set tempCol = aggColArray(i)
            computedDataDFColNames(computeColCount + i) = tempCol.AliasName
            computedDataDFColTypes(computeColCount + i) = tempCol.ColType
        Next

        ' 生成分组数量列
        If aggColCount > 0 Then
            computedDataDFColNames((computedDataDFColCount - 1)) = DF_COL_NAME_GROUP_COUNT
            computedDataDFColTypes((computedDataDFColCount - 1)) = DF_DataType.DF_INT
        End If

        ' 创建缓存
        Dim realComputedDataDF As DataFrame
        Set realComputedDataDF = New DataFrame
        realComputedDataDF.Init colNames:=computedDataDFColNames, dTypes:=computedDataDFColTypes

        Set computedDataDF = realComputedDataDF
    End If

    ' 4. 创建 group key 及其在 `indexDF` + `computedDataDF` 中的行索引映射
    If needGroup = True Then
        Set groupKeyToIndexMap = UtilsCreateSysObj.createMap
    End If

End Sub

' 为所有聚合列绑定数据源
Private Sub bindDataSourceForAggCol()
    ' 如果没有聚合列则立刻结束
    If aggColCount = 0 Then
        Exit Sub
    End If

    Dim colIdx As Integer
    With computedDataDF
        For colIdx = 0 To aggColCount
            ' 从缓存 computedDataDF 中获取指定索引的列并作为数据源绑定到聚合列上
            aggColArray(colIdx).setDataSource .getCol(computeColCount + colIdx)
        Next
    End With
End Sub

' ====================
' 筛选计算阶段
' ====================
' 执行条件筛选
Private Sub executeCondition()
    Dim i As Long
    ' 以 main DFFilter 为起点，处理所有条件，并在所有条件符合时
    ' 收集各个 Filter 的索引
    With fieldMainFilter
        For i = 0 To .UsableSize - 1
            ' 设置活动行索引
            .unsafeSetActiveUsableRowIndex i

            ' 按顺序处理每个 Filter
            doExecuteCondition(0)
        Next
    End With
End Sub

' 按照索引获取指定的条件执行器，并执行条件筛选
Private Sub doExecuteCondition(ByRef executorIndex As Integer)
    ' 1. 如果索引已经超出了条件执行器的范围，则已经完成了 join + main 条件的检查
    '    开始收集所有 DF 的索引，然后退出到上一层
    If executorIndex >= conditionExecutorCount Then
        ' 执行计算
        doCompute
        Exit Sub
    End If

    ' 2. 获取指定索引下的执行器，并执行条件筛选
    Dim executor As IDFFilterConditionExecutor
    Set executor = conditionExecutors(executorIndex)

    ' 2.1 处理 MainFilter 的执行器
    If TypeOf executor Is DFFilterMainConditionExecutor Then
        If executor.execActiveRowCheck = True Then
            ' 符合条件，则继续执行下一个 FilterExecutor；不符合则退出到上一层
            doExecuteCondition(executorIndex + 1)
        End If

        Exit Sub
    End If

    ' 2.2 处理 joinFilter 的执行器
    Dim executorFilter As DFFilter
    Set executorFilter = executor.Filter

    Dim i As Long
    With executorFilter
        If TypeOf executor Is DFFilterInnerJoinExecutor Then
            For i = 0 To .UsableSize - 1
                ' 设置活动行索引
                .unsafeSetActiveUsableRowIndex i
                ' 执行条件检查。符合条件，则继续执行下一个 FilterExecutor
                If executor.execActiveRowCheck = True Then
                    doExecuteCondition(executorIndex + 1)
                End If
            Next
        ElseIf TypeOf executor Is DFFilterLeftJoinExecutor Then
            Dim hasMatchedData As Boolean
            hasMatchedData = False
            For i = 0 To .UsableSize - 1
                ' 设置活动行索引
                .unsafeSetActiveUsableRowIndex i
                ' 执行条件检查。符合条件，则继续执行下一个 FilterExecutor
                If executor.execActiveRowCheck = True Then
                    doExecuteCondition(executorIndex + 1)
                    hasMatchedData = True
                End If
            Next

            If hasMatchedData = False Then
                ' 将当前行设置为空行，然后继续检查
                .unsafeSetActiveRowIndexIsEmpty
                doExecuteCondition(executorIndex + 1)
            End If
        Else
            Dim rightJoinExecutor As DFFilterRightJoinExecutor
            Set rightJoinExecutor = executor
            If rightJoinExecutor.isFirstExecute Then
                ' 如果是第一次访问，则所有不符合规则的索引全部保存
                rightJoinExecutor.initNoMatchedIndexes

                For i = 0 To .UsableSize - 1
                    ' 设置活动行索引
                    .unsafeSetActiveUsableRowIndex i
                    ' 执行条件检查。符合条件，则继续执行下一个 FilterExecutor
                    If executor.execActiveRowCheck = True Then
                        doExecuteCondition(executorIndex + 1)
                    Else
                        rightJoinExecutor.saveNoMatchedIndex i
                    End If
                Next
            Else
                ' 如果不是第一次访问，每次发现可以匹配的数据时，
                ' 都需要检查对应的行索引是否存在。如果存在，则进行删除
                For i = 0 To .UsableSize - 1
                    ' 设置活动行索引
                    .unsafeSetActiveUsableRowIndex i
                    ' 执行条件检查。符合条件，则继续执行下一个 FilterExecutor
                    If executor.execActiveRowCheck = True Then
                        rightJoinExecutor.saveMatchedIndex i
                        doExecuteCondition(executorIndex + 1)
                    End If
                Next
            End If
        End If

        ' 退出时将 Filter 的活动行索引回调到 0
        executorFilter.unsafeSetActiveUsableRowIndex 0
    End With
End Sub

' 处理所有未匹配的 right join 中的各行
Private Sub executeRightJoinNoMatchedRow()
    Dim executor As IDFFilterConditionExecutor
    Dim rightJoinExecutor As DFFilterRightJoinExecutor
    Dim i As Integer
    Dim noMatchedIndex As Variant

    For i = 0 To (conditionExecutorCount - 1)
        Set executor = conditionExecutors(i)

        ' 1. 搜索 right join 执行器
        If Not TypeOf executor Is DFFilterRightJoinExecutor Then
            ' 如果不是 right join 执行器，需要把当前执行器 Filter 的活动索引设置为空引用
            executor.Filter.unsafeSetActiveRowIndexIsEmpty
            Goto continue1
        End If
        Set rightJoinExecutor = executor

        ' 2. 检查是否存在未匹配的行索引
        If rightJoinExecutor.hasNoMatched = False Then
            Goto continue1
        End If

        ' 3. 遍历 right join 执行器中所有未匹配的行索引
        With executor.Filter
            For Each noMatchedIndex In rightJoinExecutor.noMatchedIndexSet.Items
                .unsafeSetActiveUsableRowIndex Int(noMatchedIndex)

                If executor.execActiveRowCheck = True Then
                    ' 如果条件匹配成功，则继续执行下一个执行器
                    doExecuteCondition(i + 1)
                Else
                    ' 条件匹配失败时，如果当前是最后一个 right join 执行器
                    ' 则
                    ' 1. 将后面的所有的执行器的活动行索引设置为空引用
                    ' 2. 执行 mainFilter 的条件执行器
                    '    如果条件匹配成功，则保存数据
                    If executor Is lastRightJoinExecutor Then
                        setAfterFilterActiveRowIsEmpty i

                        If fieldMainConditionExecutor.execActiveRowCheck = True Then
                            doCompute
                        End If
                    End If
                End If
            Next
        End With

continue1:
    Next
End Sub

' 将基准索引后的所有 Filter 活动行全部设置为空数据行
' @param baseExecutorIndex 基准索引
Private Sub setAfterFilterActiveRowIsEmpty(ByRef baseExecutorIndex As Integer)
    Dim i As Integer
    For i = baseExecutorIndex + 1 To (conditionExecutorCount - 1)
        conditionExecutors(i).Filter.unsafeSetActiveRowIndexIsEmpty
    Next
End Sub
'' 将基准索引前的所有 Filter 活动行全部设置为空数据行
'' @param baseExecutorIndex 基准索引
'Private Sub setBeforeFilterActiveRowIsEmpty(ByRef baseExecutorIndex As Integer)
'    Dim i As Integer
'    For i = 0 To baseExecutorIndex - 1
'        conditionExecutors(i).Filter.unsafeSetActiveRowIndexIsEmpty
'    Next
'End Sub
'
'' 将基准索引前的所有 Filter 活动行全部恢复
'' @param baseExecutorIndex 基准索引
'Private Sub resetBeforeFilterActiveRow(ByRef baseExecutorIndex As Integer)
'    Dim i As Integer
'    For i = 0 To baseExecutorIndex - 1
'        conditionExecutors(i).Filter.unsafeResetActiveRowIndex
'    Next
'End Sub

' 计算一行的结果
Private Sub doCompute()
    Dim f As DFFilter
    Dim colIdx As Integer
    Dim tempCol As IDFFilterCol
    If needGroup Then
        Dim aggCol As IDFFilterAggCol

        ' 计算 groupKey
        Dim groupKey As String
        groupKey = getActiveRowGroupKey

        ' 保存 groupKey 是否存在
        Dim existCurGroupKey As Boolean
        ' 表示当前 grou key 对应的最终结果的行索引
        Dim curResultSetIndex As Long

        existCurGroupKey = groupKeyToIndexMap.Exists(groupKey)
        ' 检查缓存中是否存在当前的 groupKey
        If existCurGroupKey Then
            ' 如果存在，则获取行索引
            curResultSetIndex = groupKeyToIndexMap.Item(groupKey)
        Else
            ' 如果不存在
            ' 增加最大行索引的值 maxResultRowIndex++
            maxResultRowIndex = maxResultRowIndex + 1
            curResultSetIndex = maxResultRowIndex

            ' 将当前的 group key + 行索引 保存到缓存 groupKeyToIndexMap
            groupKeyToIndexMap.Add groupKey, curResultSetIndex
        End If

        If existCurGroupKey = False Then
            ' 第一次发现这个 group key，需要在结果集中新增一行
            If needRecordFilterIndex = True Then
                ' 在缓存 indexDF 新增一行，将各个 Filter 的活动数据全部写入缓存
                With indexDF
                    .appendEmptyRow
                    For colIdx = 0 To (recordIndexFilterCount - 1)
                        .setDataByColIndex curResultSetIndex, colIdx, recordIndexFilterArray(colIdx).unsafeGetActiveRowIndex
                    Next
                End With
            End If

            If hasAggCol = True Then
                With computedDataDF
                    ' 在缓存 computedDataDF 新增一行
                    .appendEmptyRow

                    ' 计算列执行计算并写入（如果有计算列的话）
                    For colIdx = 0 To (computeColCount - 1)
                        Set tempCol = computeColArray(colIdx)
                        .setDataByColIndex curResultSetIndex, colIdx, tempCol.unsafeGetActiveRowVal
                    Next

                    ' 聚合列执行并写入计算
                    For colIdx = 0 To (aggColCount - 1)
                        Set aggCol = aggColArray(colIdx)
                        .setDataByColIndex _
                            curResultSetIndex, _
                            computeColCount + colIdx, _
                            aggCol.compute(curResultSetIndex)
                    Next

                    ' 设置分组数字段
                    .setDataByColIndex curResultSetIndex, (.ColumnCount - 1), 1
                End With
            End If
        Else
            ' 不需要新增 indexDF + computedDataDF
            If hasAggCol Then
                ' 再次计算聚合函数，并将结果写入缓存 `computedDataDF`
                With computedDataDF
                    ' 聚合列执行并写入计算
                    For colIdx = 0 To (aggColCount - 1)
                        Set aggCol = aggColArray(colIdx)
                        .setDataByColIndex _
                            curResultSetIndex, _
                            computeColCount + colIdx, _
                            aggCol.compute(curResultSetIndex)
                    Next

                    ' 设置分组数字段
                    .setDataByColIndex _
                        curResultSetIndex, (.ColumnCount - 1), _
                        .getDataByColIndex(curResultSetIndex, (.ColumnCount - 1)) + 1
                End With
            End If
        End If

    Else
        ' 增加索引数
        maxResultRowIndex = maxResultRowIndex + 1

        If needRecordFilterIndex Then
            ' 在缓存 indexDF 新增一行，将各个 Filter 的活动数据全部写入缓存
            With indexDF
                .appendEmptyRow
                For colIdx = 0 To (recordIndexFilterCount - 1)
                    .setDataByColIndex maxResultRowIndex, colIdx, recordIndexFilterArray(colIdx).unsafeGetActiveRowIndex
                Next
            End With

            With computedDataDF
                ' 计算列执行计算并写入（如果有计算列的话）
                For colIdx = 0 To (computeColCount - 1)
                    Set tempCol = computeColArray(colIdx)
                    .setDataByColIndex maxResultRowIndex, colIdx, tempCol.unsafeGetActiveRowVal
                Next
            End With
        End If
    End If
End Sub

' 生成当前活动行的 group key
Private Function getActiveRowGroupKey() As String
    getActiveRowGroupKey = ""

    ' 如果没有 groupbyCol ，默认使用空字符串
    If groupbyColCount = 0 Then
        Exit Function
    End If

    ' 执行所有列的计算，并将结果拼接成字符串
    Dim elem As Variant
    Dim c As IDFFilterCol
    For Each elem In groupbyColArray
        Set c = elem
        getActiveRowGroupKey = getActiveRowGroupKey & GROUP_KEY_COL_DELIMITER & c.unsafeGetActiveRowVal
    Next
End Function

' ====================
' 结束阶段
' ====================
Private Sub afterExec()
    ' 1. 执行所有聚合列的结束阶段的计算
    If aggColCount <> 0 Then
        Dim elem As Variant
        Dim aggCol As IDFFilterAggCol
        Dim groupCountCol As IDFSeries
        Set groupCountCol = computedDataDF.getCol(DF_COL_NAME_GROUP_COUNT)

        For Each elem In aggColArray
            Set aggCol = elem
            If aggCol.hasEndStageCompute Then
                aggCol.executeEndStageComputeByCount groupCountCol
            End If
        Next
    End If

    ' 2. 执行组合式聚合列的计算
    execComputeCompositeAggCol

    ' 3. 清空 【groupKey:行索引】 的缓存
    If Not groupKeyToIndexMap Is Nothing Then
        groupKeyToIndexMap.RemoveAll
        Set groupKeyToIndexMap = Nothing
    End If
End Sub

' 执行组合式聚合列的计算
Private Sub execComputeCompositeAggCol()
    ' 如果没有组合是聚合列，则立刻结束
    If compositeAggColCount <= 0 Then
        Exit Sub
    End If

    ' 1. 初始化缓存
    ' 1.1 收集列信息
    '     每个列的名字就是各个组合式聚合列的名字
    '     创建列名数组 + 列类型数组
    Dim dfColNames() As String
    Dim dfColTypes() As DF_DataType
    ReDim dfColNames(0 To (compositeAggColCount - 1))
    ReDim dfColTypes(0 To (compositeAggColCount - 1))

    Dim tempCol As IDFFilterCol
    Dim colIdx As Integer
    For colIdx = 0 To (compositeAggColCount - 1)
        Set tempCol = compositeAggColArray(colIdx)
        dfColNames(colIdx) = tempCol.AliasName
        dfColTypes(colIdx) = tempCol.ColType
    Next

    ' 1.2 创建缓存
    Dim realCompositeAggDF As DataFrame
    Set realCompositeAggDF = New DataFrame
    realCompositeAggDF.Init colNames:=dfColNames, dTypes:=dfColTypes
    Set compositeAggDF = realCompositeAggDF

    ' 2. 计算结果
    Dim i As Long
    Dim f As DFFilter
    Dim aggCol As IDFFilterAggCol
    Dim j As Integer
    ' 直接遍历每一行即可
    With compositeAggDF
        For i = 0 To maxResultRowIndex
            If existUsedRealColInCompositeAggCol = True Then
                ' 设置每个 Filter 的活动行索引
                For j = 0 To (recordIndexFilterCount - 1)
                    Set f = recordIndexFilterArray(j)
                    f.unsafeSetActiveRowIndex(CLng(indexDF.getDataByColIndex(i, j)))
                Next
            End If

            ' 设置基础聚合列的活动行索引
            For colIdx = 0 To (inCompositeAggColCount - 1)
                Set aggCol = inCompositeAggColArray(colIdx)
                aggCol.unsafeSetActiveRowIndex i
            Next

            ' 遍历每一个组合式聚合列完成计算
            For colIdx = 0 To (compositeAggColMap - 1)
                Set tempCol = compositeAggColArray(colIdx)

                .setDataByColIndex i, colIdx, tempCol.unsafeGetActiveRowVal
            Next
        Next
    End With
End Sub

' ====================
' 生成结果
' ====================
' 生成结果
Private Function createResultDF() As IDataFrame
    Dim result As DataFrame
    Set result = New DataFrame

    ' 1. 收集所有列
    Dim resultColArray() As IDFSeries
    ReDim resultColArray(0 To (colTypeMap.Count - 1))

    Dim nameArray As Variant
    Dim colTypeArray As Variant
    nameArray = colTypeMap.Keys
    colTypeArray = colTypeMap.Items

    Dim i As Integer
    Dim colType As Variant
    Dim series As DFSeriesInner
    Dim tempCol As IDFFilterCol
    For i = 0 To (colTypeMap.Count - 1)
        ' 搜索列对象
        colType = colTypeArray(i)

        If colType = COL_TYPE_LITERAL_COL Then
            ' 字面量列
            ' 获取类对象
            Set tempCol = fieldSelectCols.Item(nameArray(i) & "")

            ' 新建一个 IDFSeries
            Set series = New DFSeriesInner
            series.Init size:=(maxResultRowIndex + 1), dType:=tempCol.ColType
            series.IDFSeries_appendEmpty (maxResultRowIndex + 1)

            ' 计算字面量列的值，用计算结果填充整个 IDFSeries 对象
            series.IDFSeries_fillEmptySlot tempCol.unsafeGetActiveRowVal

            Set resultColArray(i) = series
        ElseIf colType = COL_TYPE_REAL_COL Then
            ' 真实列
            Set resultColArray(i) = realColIndexedSliceMap.Item(nameArray(i) & "")
        ElseIf colType = COL_TYPE_COMPUTE_COL Then
            ' 计算列
            Set resultColArray(i) = computedDataDF.getCol(nameArray(i) & "")
        ElseIf colType = COL_TYPE_AGG_COL Then
            ' 聚合列
            Set resultColArray(i) = computedDataDF.getCol(nameArray(i) & "")
        ElseIf colType = COL_TYPE_COMPOSITE_AGG_COL Then
            ' 组合式聚合列
            Set resultColArray(i) = compositeAggDF.getCol(nameArray(i) & "")
        End If
    Next

    ' 2. 初始化结果集
    result.InitBySeries resultColArray, nameArray

    Set createResultDF = result
End Function